import semver from "semver";
import { ReleaseItem } from "./jb-releases";

export type UsePlatformVersionType =
    | "build" // use `build` field from ReleaseItem
    | "version" // use `version` field from ReleaseItem
    | "build-snapshot"; // use major `build` with `-EAP-CANDIDATE-SNAPSHOT`

export const AllProductCodes = ["IIU", "GW", "GO", "PCP", "PS", "RM", "WS", "RD", "CL", "RR"] as const;
export type ProductCodes = (typeof AllProductCodes)[number];
export const AllProductIDs = [
    "intellij",
    "gateway",
    "goland",
    "pycharm",
    "phpstorm",
    "rubymine",
    "webstorm",
    "rider",
    "clion",
    "rustrover",
] as const;
export type ProductIDs = (typeof AllProductIDs)[number];

export interface TargetInfo {
    /**
     * @example intellij goland
     */
    productId: ProductIDs;
    /**
     * @example IIU GO
     */
    productCode: ProductCodes;
    /**
     * @example eap,rc,release
     */
    productType: string;
    /**
     * Examples value for different type:
     * - build 243.18137.22
     * - version 2024.3
     * - build-snapshot 243.18137-EAP-CANDIDATE-SNAPSHOT
     */
    usePlatformVersionType: "build" | "version" | "build-snapshot";
    gradlePropertiesPath: string;
    gradlePropertiesTemplate: string;
}

export interface GradleProperties {
    pluginSinceBuild: string;
    pluginUntilBuild: string;
    pluginVerifierIdeVersions: string;
    platformVersion: string;
}

export const parseGradleProperties = (content: string) => {
    const properties: Record<string, string> = {};
    content.split("\n").forEach((line) => {
        if (line.startsWith("#")) {
            return;
        }
        const [key, value] = line.split("=");
        if (key && value) {
            properties[key.trim()] = value.trim();
        }
    });
    return properties as any as GradleProperties;
};

export function parseGradlePropertiesFromTaskConfig(
    info: Pick<TargetInfo, "usePlatformVersionType">,
    targetBuild: ReleaseItem,
): GradleProperties {
    const build = targetBuild.build;
    const buildSem = semver.parse(build);
    if (!buildSem) {
        throw new Error(`Invalid build version ${build}`);
    }
    let platformVersion = build;
    switch (info.usePlatformVersionType) {
        case "build":
            platformVersion = build;
            break;
        case "version":
            platformVersion = targetBuild.version;
            break;
        case "build-snapshot":
            platformVersion = `${buildSem.major}.${buildSem.minor}-EAP-CANDIDATE-SNAPSHOT`;
            break;
    }
    return {
        pluginSinceBuild: `${buildSem.major}.${buildSem.minor}`,
        pluginUntilBuild: `${buildSem.major}.*`,
        pluginVerifierIdeVersions: targetBuild.majorVersion,
        platformVersion,
    };
}

export function renderPropertiesTemplate(
    whoami: string,
    info: Pick<TargetInfo, "gradlePropertiesTemplate">,
    properties: GradleProperties,
) {
    const { gradlePropertiesTemplate } = info;
    let newContent = gradlePropertiesTemplate;
    Object.entries(properties).forEach(([key, value]) => {
        newContent = newContent.replace(`{{${key}}}`, value);
    });
    return `# Code generated by ${whoami}. DO NOT EDIT.\n${newContent}`;
}

export const maybeCompatible = (
    newRelease: Pick<ReleaseItem, "build">,
    oldVersion: Pick<GradleProperties, "pluginSinceBuild">,
) => {
    const sinceBuild = semver.parse(`${oldVersion.pluginSinceBuild}.0`);
    const newBuild = semver.parse(newRelease.build);
    if (!sinceBuild || !newBuild) {
        return false;
    }
    const versionOK = semver.gte(newBuild, sinceBuild, false);
    const majorOK = semver.major(newBuild) === semver.major(sinceBuild);
    return versionOK && majorOK;
};
